package com.fand.platform.configuration.service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.fand.dto.PaginationDto;
import com.fand.platform.configuration.dao.DictionaryDao;
import com.fand.platform.configuration.dto.DictionaryDto;
import com.fand.platform.configuration.dto.DictionaryLaDto;
import com.fand.platform.configuration.dto.DictionaryTyDto;

/**
 * 字典服务
 * 
 * @author yaoHT
 * 
 */
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class DictionaryDefaultService implements DictionaryService {
	private DictionaryDao dictionaryDao;

	@Override
	@Transactional
	public int deleteDictionaryBy1(DictionaryDto deleteDictionary) {
		return this.dictionaryDao.deleteDictionaryBy1(deleteDictionary, new String[] {});
	}

	@Override
	@Transactional
	public int deleteDictionaryByIds(DictionaryDto deleteDictionary) {
		return this.dictionaryDao.deleteDictionaryByIds(deleteDictionary);
	}

	@Override
	@Transactional
	public int deleteDictionaryLaBy1(DictionaryLaDto deleteDictionaryLa) {
		return this.dictionaryDao.deleteDictionaryLaBy1(deleteDictionaryLa, new String[] {});
	}

	@Override
	@Transactional
	public int deleteDictionaryLaBy2(DictionaryLaDto deleteDictionaryLa) {
		return this.dictionaryDao.deleteDictionaryLaBy2(deleteDictionaryLa);
	}

	@Override
	@Transactional
	public int deleteDictionaryTyBy1(DictionaryTyDto deleteDictionaryTy) {
		return this.dictionaryDao.deleteDictionaryTyBy1(deleteDictionaryTy, new String[] {});
	}

	@Override
	@Transactional
	public int deleteDictionaryTyByIds(DictionaryTyDto deleteDictionaryTy) {
		return this.dictionaryDao.deleteDictionaryTyByIds(deleteDictionaryTy);
	}

	@Override
	public List<DictionaryDto> findDictionaryBy1(DictionaryDto findDictionary) {
		return this.dictionaryDao.selectDictionaryBy1ForMappedObjectList(DictionaryDto.class, findDictionary,
				new String[] {}, new String[] {});
	}

	@Override
	@Cacheable(value = DictionaryService.CACHE_NAME)
	public List<DictionaryDto> findDictionaryByTypeCo(String typeCo) {
		return this.dictionaryDao.selectDictionaryBy2ForMappedObjectList(DictionaryDto.class, typeCo);
	}

	@Override
	public List<DictionaryLaDto> findDictionaryLaBy1(DictionaryLaDto findDictionaryLa) {
		return this.dictionaryDao.selectDictionaryLaBy1ForMappedObjectList(DictionaryLaDto.class, findDictionaryLa,
				new String[] {}, new String[] {});
	}

	@Override
	public List<DictionaryLaDto> findDictionaryLaBy2(DictionaryLaDto findDictionaryLa) {
		return this.dictionaryDao.selectDictionaryLaBy2ForMappedObjectList(DictionaryLaDto.class, findDictionaryLa);
	}

	@Override
	public List<DictionaryTyDto> findDictionaryTyBy1(DictionaryTyDto findDictionaryTy) {
		return this.dictionaryDao.selectDictionaryTyBy1ForMappedObjectList(DictionaryTyDto.class, findDictionaryTy,
				new String[] {}, new String[] {});
	}

	@Override
	public List<DictionaryTyDto> findDictionaryTyBy2(DictionaryTyDto findDictionaryTy) {
		return this.dictionaryDao.selectDictionaryTyBy2ForMappedObjectList(DictionaryTyDto.class, findDictionaryTy);
	}

	@Override
	public DictionaryDto getDictionaryBy1(DictionaryDto getDictionary) {
		return this.dictionaryDao.selectDictionaryBy1ForMappedObject(DictionaryDto.class, getDictionary,
				new String[] {}, new String[] {});
	}

	@Override
	public DictionaryDto getDictionaryById(DictionaryDto getDictionary) {
		return this.dictionaryDao.selectDictionaryByIdForMappedObject(DictionaryDto.class, getDictionary);
	}

	@Override
	public DictionaryLaDto getDictionaryLaBy1(DictionaryLaDto getDictionaryLa) {
		return this.dictionaryDao.selectDictionaryLaBy1ForMappedObject(DictionaryLaDto.class, getDictionaryLa,
				new String[] {}, new String[] {});
	}

	@Override
	public DictionaryLaDto getDictionaryLaBy2(DictionaryLaDto getDictionaryLa) {
		return this.dictionaryDao.selectDictionaryLaBy2ForMappedObject(DictionaryLaDto.class, getDictionaryLa);
	}

	@Override
	public DictionaryTyDto getDictionaryTyBy1(DictionaryTyDto getDictionaryTy) {
		return this.dictionaryDao.selectDictionaryTyBy1ForMappedObject(DictionaryTyDto.class, getDictionaryTy,
				new String[] {}, new String[] {});
	}

	@Override
	public DictionaryTyDto getDictionaryTyById(DictionaryTyDto getDictionaryTy) {
		return this.dictionaryDao.selectDictionaryTyByIdForMappedObject(DictionaryTyDto.class, getDictionaryTy);
	}

	@Override
	public PaginationDto<DictionaryDto> paginationDictionaryBy1ForDictionaryList(DictionaryDto paginationDictionary) {
		return this.dictionaryDao.paginationDictionaryBy1ForMappedObjectList(DictionaryDto.class,
				paginationDictionary);
	}

	@Override
	public PaginationDto<Map<String, Object>> paginationDictionaryBy1ForMapList(DictionaryDto paginationDictionary) {
		return this.dictionaryDao.paginationDictionaryBy1ForMapList(paginationDictionary);
	}

	@Override
	public PaginationDto<DictionaryLaDto> paginationDictionaryLaBy1ForDictionaryLaList(
			DictionaryLaDto paginationDictionaryLa) {
		return this.dictionaryDao.paginationDictionaryLaBy1ForMappedObjectList(DictionaryLaDto.class,
				paginationDictionaryLa);
	}

	@Override
	public PaginationDto<Map<String, Object>> paginationDictionaryLaBy1ForMapList(
			DictionaryLaDto paginationDictionaryLa) {
		return this.dictionaryDao.paginationDictionaryLaBy1ForMapList(paginationDictionaryLa);
	}

	@Override
	public PaginationDto<DictionaryTyDto> paginationDictionaryTyBy1ForDictionaryTyList(
			DictionaryTyDto paginationDictionaryTy) {
		return this.dictionaryDao.paginationDictionaryTyBy1ForMappedObjectList(DictionaryTyDto.class,
				paginationDictionaryTy);
	}

	@Override
	public PaginationDto<Map<String, Object>> paginationDictionaryTyBy1ForMapList(
			DictionaryTyDto paginationDictionaryTy) {
		return this.dictionaryDao.paginationDictionaryTyBy1ForMapList(paginationDictionaryTy);
	}

	@Override
	public Integer readDictionaryBy1ForInteger(DictionaryDto readDictionary) {
		return this.dictionaryDao.selectDictionaryBy1ForObject(Integer.class, readDictionary, null, new String[] {});
	}

	@Override
	public Integer readDictionaryByCodeEqTypeIdNqIdForInteger(DictionaryDto readDictionary) {
		return this.dictionaryDao.selectDictionaryByTypeIdEqCodeNqIdForInteger(readDictionary);
	}

	@Override
	@Cacheable(value = DictionaryService.CACHE_NAME)
	public String readDictionaryByTypeCoEqCodeForId(String typeCo, String code) {
		return this.dictionaryDao.selectDictionaryByTypeCoEqCodeForId(typeCo, code);
	}

	@Override
	public Integer readDictionaryLaBy1ForInteger(DictionaryLaDto readDictionaryLa) {
		return this.dictionaryDao.selectDictionaryLaBy1ForObject(Integer.class, readDictionaryLa, null,
				new String[] {});
	}

	@Override
	public Integer readDictionaryLaBy2ForInteger(DictionaryLaDto readDictionaryLa) {
		return this.dictionaryDao.selectDictionaryLaBy2ForObject(Integer.class, readDictionaryLa, null);
	}

	@Override
	public Integer readDictionaryTyBy2ForInteger(DictionaryTyDto readDictionaryTy) {
		return this.dictionaryDao.selectDictionaryTyBy2ForObject(Integer.class, readDictionaryTy, null);
	}

	@Override
	public Integer readDictionaryTyByCodeNqIdForInteger(DictionaryTyDto readDictionaryTy) {
		return this.dictionaryDao.selectDictionaryTyByCodeNqIdForInteger(readDictionaryTy);
	}

	@Override
	public List<Integer> readListDictionaryBy1(DictionaryDto readDictionary) {
		return this.dictionaryDao.selectDictionaryBy1ForObjectList(Integer.class, readDictionary, null,
				new String[] {});
	}

	@Override
	public List<Integer> readListDictionaryBy2(DictionaryDto readDictionary) {
		return this.dictionaryDao.selectDictionaryBy2ForObjectList(Integer.class, readDictionary, null);
	}

	@Override
	public List<Integer> readListDictionaryLaBy1(DictionaryLaDto readDictionaryLa) {
		return this.dictionaryDao.selectDictionaryLaBy1ForObjectList(Integer.class, readDictionaryLa, null,
				new String[] {});
	}

	@Override
	public List<Integer> readListDictionaryLaBy2(DictionaryLaDto readDictionaryLa) {
		return this.dictionaryDao.selectDictionaryLaBy2ForObjectList(Integer.class, readDictionaryLa, null);
	}

	@Override
	public List<Integer> readListDictionaryTyBy1(DictionaryTyDto readDictionaryTy) {
		return this.dictionaryDao.selectDictionaryTyBy1ForObjectList(Integer.class, readDictionaryTy, null,
				new String[] {});
	}

	@Override
	public List<Integer> readListDictionaryTyBy2(DictionaryTyDto readDictionaryTy) {
		return this.dictionaryDao.selectDictionaryTyBy2ForObjectList(Integer.class, readDictionaryTy, null);
	}

	@Override
	@CacheEvict(value = DictionaryService.CACHE_NAME, allEntries = true)
	public void reload() {
	}

	@Override
	@Transactional
	public DictionaryDto saveDictionaryBy2ForDictionary(DictionaryDto saveDictionary) {
		DictionaryDto oldDictionary = this.dictionaryDao.selectDictionaryBy1ForMappedObject(DictionaryDto.class,
				saveDictionary, new String[] {}, new String[] {});

		if (oldDictionary == null) {
			this.dictionaryDao.insertDictionaryBy1(saveDictionary, new String[] {});

			return saveDictionary;
		}

		String[] updateProperties = com.fand.utils.BeanUtils.differProperties(saveDictionary, oldDictionary);

		if (ArrayUtils.isNotEmpty(updateProperties)) {
			this.dictionaryDao.updateDictionaryBy1(saveDictionary, updateProperties, new String[] {});
		}

		return saveDictionary;
	}

	@Override
	@Transactional
	public DictionaryDto saveDictionaryByIdOrCodeForDictionary(DictionaryDto saveDictionary) {
		String[] whereEqProperties;

		if (StringUtils.isNotBlank(saveDictionary.getId())) {
			whereEqProperties = new String[] { "id" };
		} else {
			whereEqProperties = new String[] { "typeId", "code" };
		}

		DictionaryDto oldDictionary = this.dictionaryDao.selectDictionaryBy1ForMappedObject(DictionaryDto.class,
				saveDictionary, null, whereEqProperties);

		if (oldDictionary == null) {
			saveDictionary.setId(UUID.randomUUID().toString());
			saveDictionary.setBeginDaTi(new Date());
			saveDictionary.setEndDaTi(new DateTime(9999, 12, 31, 0, 0, 0, 0).toDate());

			this.dictionaryDao.insertDictionaryBy1(saveDictionary);

			return saveDictionary;
		}

		String[] updateProperties = com.fand.utils.BeanUtils.differProperties(saveDictionary, oldDictionary, "code",
				"name", "value", "remark", "typeId", "orderNum");

		if (ArrayUtils.isNotEmpty(updateProperties)) {
			this.dictionaryDao.updateDictionaryBy1(saveDictionary, updateProperties, whereEqProperties);

			com.fand.utils.BeanUtils.copyProperties(saveDictionary, oldDictionary, updateProperties);
		}

		return oldDictionary;
	}

	@Override
	@Transactional
	public DictionaryLaDto saveDictionaryLaBy1ForDictionaryLa(DictionaryLaDto saveDictionaryLa) {
		DictionaryLaDto oldDictionaryLa = this.dictionaryDao.selectDictionaryLaBy1ForMappedObject(
				DictionaryLaDto.class, saveDictionaryLa, new String[] {}, new String[] {});

		if (oldDictionaryLa == null) {
			this.dictionaryDao.insertDictionaryLaBy1(saveDictionaryLa, new String[] {});

			return saveDictionaryLa;
		}

		String[] updateProperties = com.fand.utils.BeanUtils.differProperties(saveDictionaryLa, oldDictionaryLa);

		if (ArrayUtils.isNotEmpty(updateProperties)) {
			this.dictionaryDao.updateDictionaryLaBy1(saveDictionaryLa, updateProperties, new String[] {});
		}

		return saveDictionaryLa;
	}

	@Override
	@Transactional
	public DictionaryLaDto saveDictionaryLaBy2ForDictionaryLa(DictionaryLaDto saveDictionaryLa) {
		DictionaryLaDto oldDictionaryLa = this.dictionaryDao.selectDictionaryLaBy1ForMappedObject(
				DictionaryLaDto.class, saveDictionaryLa, new String[] {}, new String[] {});

		if (oldDictionaryLa == null) {
			this.dictionaryDao.insertDictionaryLaBy1(saveDictionaryLa, new String[] {});

			return saveDictionaryLa;
		}

		String[] updateProperties = com.fand.utils.BeanUtils.differProperties(saveDictionaryLa, oldDictionaryLa);

		if (ArrayUtils.isNotEmpty(updateProperties)) {
			this.dictionaryDao.updateDictionaryLaBy1(saveDictionaryLa, updateProperties, new String[] {});
		}

		return saveDictionaryLa;
	}

	@Override
	@Transactional
	public DictionaryTyDto saveDictionaryTyByIdOrCodeForDictionaryTy(DictionaryTyDto saveDictionaryTy) {
		String[] whereEqProperties;

		if (StringUtils.isNotBlank(saveDictionaryTy.getId())) {
			whereEqProperties = new String[] { "id" };
		} else {
			whereEqProperties = new String[] { "code" };
		}

		DictionaryTyDto oldDictionaryTy = this.dictionaryDao.selectDictionaryTyBy1ForMappedObject(
				DictionaryTyDto.class, saveDictionaryTy, null, whereEqProperties);

		if (oldDictionaryTy == null) {
			saveDictionaryTy.setId(UUID.randomUUID().toString());
			saveDictionaryTy.setBeginDaTi(new Date());
			saveDictionaryTy.setEndDaTi(new DateTime(9999, 12, 31, 0, 0, 0, 0).toDate());

			this.dictionaryDao.insertDictionaryTyBy1(saveDictionaryTy);

			return saveDictionaryTy;
		}

		String[] updateProperties = com.fand.utils.BeanUtils.differProperties(saveDictionaryTy, oldDictionaryTy,
				"code", "name", "value", "parentId", "orderNum");

		if (ArrayUtils.isNotEmpty(updateProperties)) {
			this.dictionaryDao.updateDictionaryTyBy1(saveDictionaryTy, updateProperties, whereEqProperties);

			com.fand.utils.BeanUtils.copyProperties(saveDictionaryTy, oldDictionaryTy, updateProperties);
		}

		return oldDictionaryTy;
	}

	@Override
	@Transactional
	public int saveDictionaryTyByMoveObject(DictionaryTyDto saveDictionaryTy) {
		return this.dictionaryDao.updateDictionaryTyByMove(saveDictionaryTy);
	}

	@Override
	@Transactional
	public int setDictionaryBy1(DictionaryDto setDictionary) {
		return this.dictionaryDao.updateDictionaryBy1(setDictionary, new String[] {}, new String[] {});
	}

	@Override
	@Transactional
	public int setDictionaryBy2(DictionaryDto setDictionary) {
		return this.dictionaryDao.updateDictionaryBy2(setDictionary);
	}

	@Override
	@Transactional
	public int setDictionaryLaBy1(DictionaryLaDto setDictionaryLa) {
		return this.dictionaryDao.updateDictionaryLaBy1(setDictionaryLa, new String[] {}, new String[] {});
	}

	@Override
	@Transactional
	public int setDictionaryLaBy2(DictionaryLaDto setDictionaryLa) {
		return this.dictionaryDao.updateDictionaryLaBy2(setDictionaryLa);
	}

	@Override
	@Transactional
	public int setDictionaryTyBy1(DictionaryTyDto setDictionaryTy) {
		return this.dictionaryDao.updateDictionaryTyBy1(setDictionaryTy, new String[] {}, new String[] {});
	}

	@Override
	@Transactional
	public int setDictionaryTyBy2(DictionaryTyDto setDictionaryTy) {
		return this.dictionaryDao.updateDictionaryTyBy2(setDictionaryTy);
	}

	@Override
	public List<DictionaryTyDto> treeDictionaryTyByParentId(final DictionaryTyDto selectDictionaryTy) {
		final List<DictionaryTyDto> dictionaryTyList = this.dictionaryDao
				.selectDictionaryTyByParentIdNqIdForMappedObjectList(DictionaryTyDto.class, selectDictionaryTy);

		if (CollectionUtils.isEmpty(dictionaryTyList)) {
			return dictionaryTyList;
		}

		for (final DictionaryTyDto dictionaryTyDto : dictionaryTyList) {
			if (StringUtils.isBlank(dictionaryTyDto.getId())) {
				continue;
			}

			final DictionaryTyDto childSelectDictionaryTy = new DictionaryTyDto();

			org.springframework.beans.BeanUtils.copyProperties(selectDictionaryTy, childSelectDictionaryTy);

			childSelectDictionaryTy.setParentId(dictionaryTyDto.getId());

			final List<DictionaryTyDto> childs = this.dictionaryDao
					.selectDictionaryTyByParentIdNqIdForMappedObjectList(DictionaryTyDto.class,
							childSelectDictionaryTy);

			dictionaryTyDto.setChilds(childs);
		}

		return dictionaryTyList;
	}
}